package view;


import javax.swing.*;
import java.awt.*;

/**
 * Author: Mr.Zhao, Time: 2018/4/27/21:29
 * Description: 棋盘
 */
public class ChessBoard extends JPanel {

    /* 一个格子的宽度，单位:像素 */
    private int cellWidth;

    /* 一个格子的高度，单位：像素 */
    private int cellHeight;

    /* 用格子表示的宽度，（宽度为多少个格子），单位：格 */
    public static final int WIDTH = 8;

    /* 用格子表示的高度，（高度为多少个格子），单位：格，
        其中第5格为“楚河汉界”字样 */
    public static final int HEIGHT = 9;

    /* 棋盘边距，单位：像素 */
    private int margin;

    /* 棋盘背景颜色（不算边框) */
    private static final Color BACKGROUND_COLOR = Color.WHITE;

    /* 线条以及字体的颜色 */
    private static final Color LINE_COLOR = new Color(0xFFBC9F77);

    /* 线条的粗细 */
    private static final float LINE_SIZE = 2.0f;

    /* 楚河汉界字体 */
    private static Font CHHJ_FONT;

    /* 单例模式 */
    private static ChessBoard instance = null;

    private ChessBoard() {
        this.setLayout(null);
        /* 根据屏幕分辨率计算所需的单元格大小 */
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        cellWidth = cellHeight = screenSize.height / 11;
        margin = screenSize.height / 26;
        CHHJ_FONT = new Font("隶书", Font.BOLD | Font.ITALIC, (int) (cellHeight * 0.6));
        this.setSize(WIDTH * cellWidth + margin * 2, HEIGHT * cellHeight + margin * 2);
    }

    /**
     * 获得单例。
     * 之所以使用单利模式，是因为棋盘的大小不是固定的，不能写成类变量。
     * 在棋盘初始化时需要获得当前设备的分辨率从而确定大小，而其他地方会用到该棋盘的尺寸，
     * 如果其他类在棋盘对象创建之前就实例化了，那么将无法得到棋盘的尺寸。
     *
     * @return
     */
    public static ChessBoard getInstance() {
        if (instance == null) {
            instance = new ChessBoard();
        }
        return instance;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // System.out.println("ChessBoard paintComponent");
        //填充整个面板背景色
        g.setColor(UIManager.getColor("control"));
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
        // 填充棋盘背景色
        g.setColor(BACKGROUND_COLOR);
        g.fillRect(margin, margin, WIDTH * cellWidth, HEIGHT * cellHeight);

        // 设置线的粗细以及颜色
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(LINE_SIZE));
        g2.setColor(LINE_COLOR);

        // 横线
        for (int i = 0; i <= HEIGHT; i++) {
            g2.drawLine(margin, i * cellHeight + margin,
                    WIDTH * cellWidth + margin, i * cellHeight + margin);
        }
        // 竖线
        for (int i = 0; i <= WIDTH; i++) {
            g2.drawLine(i * cellWidth + margin, margin,
                    i * cellWidth + margin, HEIGHT * cellHeight + margin);
        }
        // 交叉线
        g2.drawLine(margin + cellWidth * 3, margin, margin + cellWidth * 5,
                margin + cellHeight * 2);
        g2.drawLine(margin + cellWidth * 5, margin, margin + cellWidth * 3,
                margin + cellHeight * 2);
        g2.drawLine(margin + cellWidth * 3, margin + cellHeight * 7,
                margin + cellWidth * 5, margin + cellHeight * 9);
        g2.drawLine(margin + cellWidth * 5, margin + cellHeight * 7,
                margin + cellWidth * 3, margin + cellHeight * 9);


        drawCornerLine(g2, 1, 2);
        drawCornerLine(g2, 7, 2);
        drawCornerLine(g2, 1, 7);
        drawCornerLine(g2, 7, 7);
        for (int i = 0; i <= 8; i += 2) {
            drawCornerLine(g2, i, 3);
            drawCornerLine(g2, i, 6);
        }


        // 楚河汉界
        g.setColor(BACKGROUND_COLOR);
        g.fillRect((int) (margin + LINE_SIZE), (int) (margin + cellHeight * 4 + LINE_SIZE),
                (int) (cellWidth * 8 - LINE_SIZE * 2), (int) (cellHeight - LINE_SIZE * 2));

        g.setColor(LINE_COLOR);
        g.setFont(CHHJ_FONT);

        // System.out.println("绘制楚河汉界");
        g.drawString("楚 河", (margin + cellWidth), (int) (margin + cellHeight * 4 + cellHeight * 0.7));
        g.drawString("汉 界", (margin + cellWidth * 5), (int) (margin + cellHeight * 4 + cellHeight * 0.7));

        //
    }

    /**
     * 画炮及卒所在位置的边角线
     *
     * @param g
     * @param x 要画点的横坐标，单位：格
     * @param y 纵坐标，单位：格
     */
    private void drawCornerLine(Graphics g, int x, int y) {
        //线长
        int lineLength = cellWidth / 8;
        //空隙大小
        float space = cellWidth / 18;

        if (x != 0) {
            //左上横
            g.drawLine((int) (margin + x * cellWidth - lineLength - space), (int) (margin + y * cellHeight - space),
                    (int) (margin + x * cellWidth - space), (int) (margin + y * cellHeight - space));
            //左下横
            g.drawLine((int) (margin + x * cellWidth - lineLength - space), (int) (margin + y * cellHeight + space),
                    (int) (margin + x * cellWidth - space), (int) (margin + y * cellHeight + space));
            //左上竖
            g.drawLine((int) (margin + x * cellWidth - space), (int) (margin + y * cellHeight - space - lineLength),
                    (int) (margin + x * cellWidth - space), (int) (margin + y * cellHeight - space));
            //左下竖
            g.drawLine((int) (margin + x * cellWidth - space), (int) (margin + y * cellHeight + space),
                    (int) (margin + x * cellWidth - space), (int) (margin + y * cellHeight + space + lineLength));
        }
        if (x != WIDTH) {
            //右上横
            g.drawLine((int) (margin + x * cellWidth + space), (int) (margin + y * cellHeight - space),
                    (int) (margin + x * cellWidth + lineLength + space), (int) (margin + y * cellHeight - space));
            //右下横
            g.drawLine((int) (margin + x * cellWidth + space), (int) (margin + y * cellHeight + space),
                    (int) (margin + x * cellWidth + lineLength + space), (int) (margin + y * cellHeight + space));
            //右上竖
            g.drawLine((int) (margin + x * cellWidth + space), (int) (margin + y * cellHeight - space - lineLength),
                    (int) (margin + x * cellWidth + space), (int) (margin + y * cellHeight - space));
            //右下竖
            g.drawLine((int) (margin + x * cellWidth + space), (int) (margin + y * cellHeight + space),
                    (int) (margin + x * cellWidth + space), (int) (margin + y * cellHeight + space + lineLength));
        }
    }

    public int getMargin() {
        return margin;
    }

    public int getCellWidth() {
        return cellWidth;
    }

    public int getCellHeight() {
        return cellHeight;
    }
}
